﻿#pragma once
//字符串辅助类
#include <sstream>
#include <vector>
#include <string>
#include "Convert.h"
namespace str{



/************************************************************
1、字符串格式化
    提供类似printf的字符串格式化功能，支持参数自动识别，弥补printf的缺陷
*************************************************************/
//获取数据
template <typename T>
T DataTraits(T val)
{
    return val;
}

//特化
const char* DataTraits(const std::string& ref);

//类型萃取，对非基础类型，按照c++的方式来处理
template <typename T>
std::string TypeTraits(void (T::*)())
{
	return std::string();
}

template <typename T>
T TypeTraits(T val)
{
	return val;
}

//类型萃取,数据转换
template <typename T>
std::string TypeTraitsValue(T val, int T::*)
{
	std::stringstream str;
	str << val;
	return str.str();
}

template <typename T>
T TypeTraitsValue(T val, ...)
{
	return val;
}

template<typename T>
decltype(TypeTraits<T>(0)) ClassTraits(T val)
{
	return TypeTraitsValue<T>(val, 0);
}

//格式化
std::string __format(const char *strFmt, ...);

template<typename...Args>
std::string __args(const char *strFmt, Args...args)
{
    return __format(strFmt, DataTraits(std::forward<Args>(args))...);
}

template<typename...Args>
std::string format(const char *strFmt, Args...args)
{
    return __args(strFmt, ClassTraits(std::forward<Args>(args))...);
}

std::string format(const char *strFmt);


/************************************************************
2、基于位置的格式化
    提供基于位置的参数格式化方式
*************************************************************/

//参数包装，统一转化成Param类
template<typename T>
std::string Param(T& val)
{
	std::stringstream str;
	str << val;
	return str.str();
};
//特化
template<typename T = std::string>
std::string& Param(std::string& val)
{
	return val;
};

//特化
template<typename T = const char*>
std::string Param(const char* val)
{
	return val;
};

//参数搜集器，负责收集参数，并将参数格式化输出
class VCollect
{
public:
	VCollect(const char* pszContext) :m_pszContext(pszContext)
	{

	}

	//递归结束，将结果返回
	std::string PosFormat()
	{
		return GetString();
	}

	template<typename T, typename ...Args>
	std::string PosFormat(T val, Args...args)
	{
		m_vecParam.emplace_back(Param(val));
		return PosFormat(args...);
	}

	std::string GetString()
	{
		std::stringstream str;
		const char* s = m_pszContext;
		while (*s)
		{
			if (*s == '%')
			{
				char ch = atoi(++s);
				if (ch == '%')
				{
					str << *s;
					continue;
				}
				int nArgNum = atoi(s++);
				if (nArgNum <= 0 || nArgNum > m_vecParam.size())
				{
					return str.str();
				}

				str << m_vecParam[nArgNum - 1];
				while ((nArgNum = nArgNum / 10) > 0)s++;
			}
			else
			{
				str << *s++;
			}

		}
		return std::move(str.str());
	}
private:
	std::vector<std::string> m_vecParam;
	const char* m_pszContext;
};


//按占位符替换参数，使用方法  format_pos("%1 + %2 = %3", 1,2,"3")
template<typename...Args>
std::string format_pos(const char *strFmt, Args...args)
{
    return VCollect(strFmt).PosFormat(args...);
}

//特化，实现未带参数场景
std::string format_pos(const char *strFmt);
/************************************************************
3、串接字符串
    将容器中的数据串接成字符串
*************************************************************/
template<typename T,
	typename std::enable_if<
		std::is_same<typename T::iterator, decltype(std::declval<T>().begin())>::value
		&& std::is_same<typename T::iterator, decltype(std::declval<T>().end())>::value,
		int>::type N = 0 >
		std::string concat(T& vecData, const std::string& delim = ",")
{
    if (vecData.size() <= 0)
    {
        return std::string();
    }
    std::stringstream ss;
    for (auto item : vecData)
    {
        ss << delim << item;
    }

    return ss.str().substr(delim.length());
}


/************************************************************
4、串接字符串
    将定制的参数列表串接成字符串
*************************************************************/
/*
递归终止函数
*/
template<char S = '-',class Tail>
std::string join(Tail val)
{
	std::ostringstream oss;
	oss << val;
    return oss.str();
}

/*
sep 分隔符
head 第一个参数
*/
/* 构建string key，以第一参数为分隔符 */
template<char S = '-', class T, class ...Arg>
std::string join(T head, Arg ...args)
{
    std::ostringstream oss;
	oss << head << S << join<S>(args...);
	return oss.str();
}

/************************************************************
4、字符串切割函数
*************************************************************/
template<typename T = std::string>
std::vector<T> split(const std::string& strContext, const std::string& delim = " ",bool ignoreMul = false)
{
	std::vector<T> vecVal;
	size_t last = 0;
	size_t index = 0;
	while ((index = strContext.find_first_of(delim,last)) !=std::string::npos)
	{
		if (index == last && ignoreMul)
		{
			last++;
			continue;
		}
		vecVal.push_back(Convert<T>(strContext.substr(last,index-last)));
		last=index+1;
	}
	if (strContext.size() > last || !ignoreMul)
	{
		vecVal.push_back(Convert<T>(strContext.substr(last)));
	}
	return vecVal;
}

//以N结尾系列函数未不改变原值，返回新的值
/************************************************************
5、转换成小写
*************************************************************/
//转换大小写
std::string& to_lower(std::string& str);
std::string to_lower_c(const std::string& strVal);

/************************************************************
6、转换成大写
*************************************************************/
std::string& to_upper(std::string& str);
std::string to_upper_c(const std::string& strVal);


/************************************************************
7、去除左空格
*************************************************************/
std::string& ltrim(std::string& strVal, const char* pszDef = " \n\r\t");

/************************************************************
8、去除右空格
*************************************************************/
std::string& rtrim(std::string& strVal, const char* pszDef = " \n\r\t");

/************************************************************
9、去除前后空格
*************************************************************/
std::string& trim(std::string& strVal, const char* pszDef = " \n\r\t");

/************************************************************
10、替换所有匹配的子字符串
*************************************************************/
std::string& replace_all(std::string& strVal, const std::string& oldStr, const std::string& newStr);

/************************************************************
10、截取子字符串
*************************************************************/
//从指定位置截取到匹配到的字符，删除改部分数据并将该部分数据返回
std::string cutstr(std::string& strVal, const std::string& strEnd, int nPos = 0);
//从指定位置开始匹配开始字符和结束字符，
std::string cutstr(std::string& strVal, const std::string& strStart, const std::string& strEnd, int nPos = 0);

std::string cutstr_c(const std::string& strVal, const std::string& strEnd, int nPos = 0);
std::string cutstr_c(const std::string& strVal, const std::string& strStart, const std::string& strEnd, int nPos = 0);
}